package qyWechat

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
)

const (
	sendMsgUrl         = "https://qyapi.weixin.qq.com/cgi-bin/message/send"
	updateTaskCardUrl  = "https://qyapi.weixin.qq.com/cgi-bin/message/update_taskcard"
	updateTemplateCard = "https://qyapi.weixin.qq.com/cgi-bin/message/update_template_card"
)

// 更新任务卡片
func (w *QyWechat) UpdateTaskCard(userIds []string, agentId int, taskId, clickedKey string) (err error) {
	var v = map[string]interface{}{
		"userids":     userIds,
		"agentid":     agentId,
		"task_id":     taskId,
		"clicked_key": clickedKey,
	}
	data, err := json.Marshal(v)
	if err != nil {
		return
	}
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(updateTaskCardUrl+"?access_token="+token, "application/json;charset=UTF-8", bytes.NewReader(data))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	var m SendMsgResult
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	return
}

// 更新模板卡片
func (w *QyWechat) UpdateTemplateCard(responseCode string, agentId int, replaceName string) (err error) {
	var v = map[string]interface{}{
		"userids":       make([]string, 0),
		"agentid":       agentId,
		"atall":         1,
		"response_code": responseCode,
		"button":        map[string]string{"replace_name": replaceName},
	}
	data, err := json.Marshal(v)
	if err != nil {
		return
	}
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(updateTemplateCard+"?access_token="+token, "application/json;charset=UTF-8", bytes.NewReader(data))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	var m SendMsgResult
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	return
}

type SendMsgResult struct {
	ErrCode      int    `json:"errcode"`
	ErrMsg       string `json:"errmsg"`
	InvalidUser  string `json:"invaliduser"`
	InvalidParty string `json:"invalidparty"`
	InvalidTag   string `json:"invalidtag"`
	MsgId        string `json:"msgid"`
	ResponseCode string `json:"response_code"`
}

func (w *QyWechat) sendByte(data []byte) (m SendMsgResult, err error) {
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(sendMsgUrl+"?access_token="+token, "application/x-www-form-urlencoded", bytes.NewReader(data))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return m, errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	return
}
func (w *QyWechat) SendString(jsonStr string) (err error) {
	_, err = w.sendByte([]byte(jsonStr))
	return
}

func (w *QyWechat) SendString2(jsonStr string) (s SendMsgResult, err error) {
	return w.sendByte([]byte(jsonStr))
}

func (w *QyWechat) sendMsg(req interface{}) (err error) {
	data, err := json.Marshal(req)
	if err != nil {
		return
	}
	_, err = w.sendByte(data)
	return
}

// 发送文本消息
func (w *QyWechat) SendText(toUser, toParty, toTag string, content string) (err error) {
	return w.sendMsg(NewTextSendMessage(toUser, toParty, toTag, w.AgentId, content))
}

// 发送图片消息
func (w *QyWechat) SendImage(toUser, toParty, toTag string, mediaId string) (err error) {
	return w.sendMsg(NewImageSendMessage(toUser, toParty, toTag, w.AgentId, mediaId))
}

// 发送语音消息
func (w *QyWechat) SendVoice(toUser, toParty, toTag string, mediaId string) (err error) {
	return w.sendMsg(NewVoiceSendMessage(toUser, toParty, toTag, w.AgentId, mediaId))
}

// 发送视频消息
func (w *QyWechat) SendVideo(toUser, toParty, toTag string, mediaId, title, description string) (err error) {
	return w.sendMsg(NewVideoSendMessage(toUser, toParty, toTag, w.AgentId, mediaId, title, description))
}

// 发送文件消息
func (w *QyWechat) SendFile(toUser, toParty, toTag string, mediaId string) (err error) {
	return w.sendMsg(NewFileSendMessage(toUser, toParty, toTag, w.AgentId, mediaId))
}

// 发送文本卡片消息
func (w *QyWechat) SendTextCard(toUser, toParty, toTag string, title, description, url string) (err error) {
	return w.sendMsg(NewTextCardSendMessage(toUser, toParty, toTag, w.AgentId, title, description, url))
}

// 发送图文消息
func (w *QyWechat) SendNews(toUser, toParty, toTag string, articles []Article) (err error) {
	return w.sendMsg(NewNewsSendMessage(toUser, toParty, toTag, w.AgentId, articles))
}

// 发送markdown消息
func (w *QyWechat) SendMarkDown(toUser, toParty, toTag string, context string) (err error) {
	return w.sendMsg(NewMarkDownSendMessage(toUser, toParty, toTag, w.AgentId, context))
}

// 发送任务卡片消息
func (w *QyWechat) SendTaskCard(toUser, toParty, toTag string, taskCard TaskCard) (err error) {
	return w.sendMsg(NewTaskCardSendMessage(toUser, toParty, toTag, w.AgentId, taskCard))
}

/* 构建结构 */
type baseSendMessage struct {
	ToUser                 string `json:"touser"`
	ToParty                string `json:"toparty"`
	ToTag                  string `json:"totag"`
	MsgType                string `json:"msgtype"`
	AgentId                int    `json:"agentid"`
	EnableDuplicateCheck   int    `json:"enable_duplicate_check"`
	DuplicateCheckInterval int    `json:"duplicate_check_interval"`
}

// 文本
type TextSendMessage struct {
	baseSendMessage
	Text          Text `json:"text"`
	Safe          int  `json:"safe"`
	EnableIdTrans int  `json:"enable_id_trans"`
}
type Text struct {
	Content string `json:"content"`
}

func NewTextSendMessage(toUser, toParty, toTag string, agentId int, content string) TextSendMessage {
	return TextSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"text",
			agentId,
			0,
			1800,
		},
		Text{Content: content},
		0,
		0,
	}
}

// 图片
type ImageSendMessage struct {
	baseSendMessage
	Image Image `json:"image"`
	Safe  int   `json:"safe"`
}
type Image struct {
	MediaId string `json:"media_id"`
}

func NewImageSendMessage(toUser, toParty, toTag string, agentId int, mediaId string) ImageSendMessage {
	return ImageSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"image",
			agentId,
			0,
			1800,
		},
		Image{MediaId: mediaId},
		0,
	}
}

// 语音
type VoiceSendMessage struct {
	baseSendMessage
	Voice Voice `json:"voice"`
}
type Voice struct {
	MediaId string `json:"media_id"`
}

func NewVoiceSendMessage(toUser, toParty, toTag string, agentId int, mediaId string) VoiceSendMessage {
	return VoiceSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"voice",
			agentId,
			0,
			1800,
		},
		Voice{MediaId: mediaId},
	}
}

// 视频
type VideoSendMessage struct {
	baseSendMessage
	Video Video `json:"video"`
	Safe  int   `json:"safe"`
}
type Video struct {
	MediaId     string `json:"media_id"`
	Title       string `json:"title"`
	Description string `json:"description"`
}

func NewVideoSendMessage(toUser, toParty, toTag string, agentId int, mediaId, title, description string) VideoSendMessage {
	return VideoSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"video",
			agentId,
			0,
			1800,
		},
		Video{MediaId: mediaId, Title: title, Description: description},
		0,
	}
}

// 文件
type FileSendMessage struct {
	baseSendMessage
	File File `json:"file"`
	Safe int  `json:"safe"`
}
type File struct {
	MediaId string `json:"media_id"`
}

func NewFileSendMessage(toUser, toParty, toTag string, agentId int, mediaId string) FileSendMessage {
	return FileSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"file",
			agentId,
			0,
			1800,
		},
		File{MediaId: mediaId},
		0,
	}
}

// 文本卡片
type TextCardSendMessage struct {
	baseSendMessage
	TextCard      TextCard `json:"textcard"`
	EnableIdTrans int      `json:"enable_id_trans"`
}
type TextCard struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Url         string `json:"url"`
	BtnTxt      string `json:"btntxt"`
}

func NewTextCardSendMessage(toUser, toParty, toTag string, agentId int, title, description, url string) TextCardSendMessage {
	return TextCardSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"textcard",
			agentId,
			0,
			1800,
		},
		TextCard{Title: title, Description: description, Url: url, BtnTxt: "详情"},
		0,
	}
}

// 图文
type NewsSendMessage struct {
	baseSendMessage
	News          News `json:"news"`
	EnableIdTrans int  `json:"enable_id_trans"`
}
type News struct {
	Articles []Article `json:"articles"`
}
type Article struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Url         string `json:"url"`
	PicUrl      string `json:"picurl"`
}

func NewNewsSendMessage(toUser, toParty, toTag string, agentId int, articles []Article) NewsSendMessage {
	return NewsSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"news",
			agentId,
			0,
			1800,
		},
		News{Articles: articles},
		0,
	}
}

// markdown
type MarkDownSendMessage struct {
	baseSendMessage
	MarkDown MarkDown `json:"markdown"`
}
type MarkDown struct {
	Content string `json:"content"`
}

func NewMarkDownSendMessage(toUser, toParty, toTag string, agentId int, content string) MarkDownSendMessage {
	return MarkDownSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"markdown",
			agentId,
			0,
			1800,
		},
		MarkDown{Content: content},
	}
}

// 任务卡片
type TaskCardSendMessage struct {
	baseSendMessage
	TaskCard      TaskCard `json:"taskcard"`
	EnableIdTrans int      `json:"enableIdTrans"`
}
type TaskCard struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Url         string `json:"url"`
	TaskId      string `json:"task_id"`
	Btn         []Btn  `json:"btn"`
}
type Btn struct {
	Key         string `json:"key"`
	Name        string `json:"name"`
	ReplaceName string `json:"replace_name"`
	Color       string `json:"color"`
	IsBold      bool   `json:"is_bold"`
}

func NewTaskCardSendMessage(toUser, toParty, toTag string, agentId int, taskCard TaskCard) TaskCardSendMessage {
	return TaskCardSendMessage{
		baseSendMessage{
			toUser,
			toParty,
			toTag,
			"taskcard",
			agentId,
			0,
			1800,
		},
		taskCard,
		0,
	}
}
